﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 微云缓存服务实现
    /// </summary>
    public class CacheDataService : ICacheDataService
    {
        /// <summary>
        /// 初始化一个微云缓存服务实现 <see cref="CacheDataService"/> 的新实例
        /// </summary>
        /// <param name="provider"></param>
        public CacheDataService(IServiceProvider provider)
        {
            ServiceProvider = provider;
            Logger = provider.GetLogger(GetType());

            //创建线程
            Thread thread = new Thread(ClearExpiredCache)
            {
                IsBackground = true//这个是把我们这个线程放到后台线程里面执行
            };
            thread.Start();//Start就代表开始执行线程
        }

        #region 属性
        /// <summary>
        /// 获取 服务提供者对象
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }
      
        /// <summary>
        /// 获取 日志对象
        /// </summary>
        protected ILogger Logger { get; }
      
        /// <summary>
        /// 获取 缓存数据集合
        /// </summary>
        private static List<CacheData> CacheDataList { get; } = new List<CacheData>();

        #endregion

        #region 同步
        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        public CacheData Get(object Key)
        {
            var existData = CacheDataList.FirstOrDefault(o => o.Key.Equals(Key));
            return existData;
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="Group">缓存键</param>
        public List<CacheData> GetByGroup(object Group)
        {
            var existDataList = CacheDataList.FindAll(o => o.Group.Equals(Group));
            return existDataList;
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        public List<CacheData> GetAll()
        {
            return CacheDataList;
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        /// <param name="Value">缓存值</param>
        /// <param name="Type">缓存类型</param>
        /// <param name="Group">缓存分组</param>
        /// <param name="expiresUtc">过期时间UTC标准</param>
        public void Set(object Key, object Value, object Type, object Group, DateTime? expiresUtc = null)
        {
            if (Key == null)
            {
                //throw new MicroCloudException("缓存键不能为空");
                throw new Exception(I18N.T("缓存键不能为空"));
            }
            var existData = CacheDataList.FirstOrDefault(o => o.Key.Equals(Key));
            if (existData != null)
            {
                existData.Value = Value;
                existData.Type = Type;
                existData.Group = Group;
                existData.ExpiresUtc = expiresUtc;
            }
            else
            {
                var cacheData = new CacheData(Key, Value, Type, Group, expiresUtc);
                CacheDataList.Add(cacheData);
            }
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        public void Remove(object Key)
        {
            if (Key == null)
            {
                throw new Exception(I18N.T("缓存键不能为空"));
            }
            var existData = CacheDataList.FirstOrDefault(o => o.Key.Equals(Key));
            if (existData != null)
            {
                CacheDataList.Remove(existData);
            }
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="Group">缓存分组</param>
        public void RemoveByGroup(object Group)
        {
            CacheDataList.RemoveAll(o => o.Group.Equals(Group));
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="Key">缓存键</param>
        public bool IsExisted(object Key)
        {
            return CacheDataList.Exists(o => o.Key.Equals(Key));
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="Group">缓存分组</param>
        public bool IsExistedByGroup(object Group)
        {
            return CacheDataList.Exists(o => o.Group.Equals(Group));
        }

        #endregion

        #region 异步
        /// <summary>
        /// 异步获取缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        public async Task<CacheData> GetAsync(object Key)
        {
            var existData = Get(Key);
            return await Task.Factory.StartNew(() => existData);
        }

        /// <summary>
        /// 异步获取缓存
        /// </summary>
        /// <param name="Group">缓存键</param>
        public async Task<List<CacheData>> GetByGroupAsync(object Group)
        {
            var existDataList = GetByGroup(Group);
            return await Task.Factory.StartNew(() => existDataList);
        }

        /// <summary>
        /// 异步获取缓存
        /// </summary>
        public async Task<List<CacheData>> GetAllAsync()
        {
            var existDataList = GetAll();
            return await Task.Factory.StartNew(() => existDataList);
        }

        /// <summary>
        /// 异步设置缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        /// <param name="Value">缓存值</param>
        /// <param name="Type">缓存类型</param>
        /// <param name="Group">缓存分组</param>
        /// <param name="expiresUtc">过期时间UTC标准</param>
        public async Task SetAsync(object Key, object Value, object Type, object Group, DateTime? expiresUtc = null)
        {
            Set(Key, Value, Type, Group, expiresUtc);
            await Task.CompletedTask;
        }

        /// <summary>
        /// 异步移除缓存
        /// </summary>
        /// <param name="Key">缓存键</param>
        public async Task RemoveAsync(object Key)
        {
            Remove(Key);
            await Task.CompletedTask;
        }

        /// <summary>
        /// 异步移除缓存
        /// </summary>
        /// <param name="Group">缓存分组</param>
        public async Task RemoveByGroupAsync(object Group)
        {
            RemoveByGroup(Group);
            await Task.CompletedTask;
        }

        /// <summary>
        /// 异步是否存在
        /// </summary>
        /// <param name="Key">缓存键</param>
        public async Task<bool> IsExistedAsync(object Key)
        {
            var isExisted = IsExisted(Key);
            return await Task.Factory.StartNew(() => isExisted);
        }

        /// <summary>
        /// 异步是否存在
        /// </summary>
        /// <param name="Group">缓存分组</param>
        public async Task<bool> IsExistedByGroupAsync(object Group)
        {
            var isExisted = IsExistedByGroup(Group);
            return await Task.Factory.StartNew(() => isExisted);
        }

        #endregion

        #region 辅助方法
        /// <summary>
        /// 清除过期缓存
        /// </summary>
        private static void ClearExpiredCache()
        {
            var isWhile = true;
            while (isWhile)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));

                var nowUTC = DateTime.UtcNow;
                CacheDataList.RemoveAll(o => o.ExpiresUtc < nowUTC);
            }
        }

        #endregion
    }
}
